home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / crctable.zip / CRCTABLE.PAS < prev    next >
Pascal/Delphi Source File  |  1990-12-03  |  22KB  |  512 lines

  1. {$A+,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
  2.  
  3.                                         (*
  4.  
  5.      CRCTABLE.PAS
  6.      (C) Copyright 1990 Dan Melton
  7.      All Rights Reserved
  8.  
  9.      Credit for the values of the CRCTAB_32 goes to Gary S. Brown.  The text
  10.      from which the tables were derived from is at the end of the assembly
  11.      language source code.
  12.  
  13.      The assembly source code is appended to this TP program; the compiler
  14.      uses the "END." statement as the end of source code marker.
  15.      Nothing past "END." is processed by the Turbo Pascal compiler.
  16.  
  17.                                         *)
  18.  
  19. unit CRCTABLE;
  20.  
  21. interface
  22.  
  23. function CRC16 (B : byte; CRC : word) : word;
  24. function CRC32 (B : byte; CRC : longint) : longint;
  25. function CRC16BUF (BSEG,BOFS,BLEN : word; CRC : word) : word;
  26. function CRC32BUF (BSEG,BOFS,BLEN : word; CRC : longint) : longint;
  27.  
  28. implementation
  29.  
  30. const
  31.   CRCTAB_16 : array [0..255] of word
  32.             = ( $0000,  $1021,  $2042,  $3063,  $4084,  $50A5,  $60C6,  $70E7,
  33.                 $8108,  $9129,  $A14A,  $B16B,  $C18C,  $D1AD,  $E1CE,  $F1EF,
  34.                 $1231,  $0210,  $3273,  $2252,  $52B5,  $4294,  $72F7,  $62D6,
  35.                 $9339,  $8318,  $B37B,  $A35A,  $D3BD,  $C39C,  $F3FF,  $E3DE,
  36.                 $2462,  $3443,  $0420,  $1401,  $64E6,  $74C7,  $44A4,  $5485,
  37.                 $A56A,  $B54B,  $8528,  $9509,  $E5EE,  $F5CF,  $C5AC,  $D58D,
  38.                 $3653,  $2672,  $1611,  $0630,  $76D7,  $66F6,  $5695,  $46B4,
  39.                 $B75B,  $A77A,  $9719,  $8738,  $F7DF,  $E7FE,  $D79D,  $C7BC,
  40.                 $48C4,  $58E5,  $6886,  $78A7,  $0840,  $1861,  $2802,  $3823,
  41.                 $C9CC,  $D9ED,  $E98E,  $F9AF,  $8948,  $9969,  $A90A,  $B92B,
  42.                 $5AF5,  $4AD4,  $7AB7,  $6A96,  $1A71,  $0A50,  $3A33,  $2A12,
  43.                 $DBFD,  $CBDC,  $FBBF,  $EB9E,  $9B79,  $8B58,  $BB3B,  $AB1A,
  44.                 $6CA6,  $7C87,  $4CE4,  $5CC5,  $2C22,  $3C03,  $0C60,  $1C41,
  45.                 $EDAE,  $FD8F,  $CDEC,  $DDCD,  $AD2A,  $BD0B,  $8D68,  $9D49,
  46.                 $7E97,  $6EB6,  $5ED5,  $4EF4,  $3E13,  $2E32,  $1E51,  $0E70,
  47.                 $FF9F,  $EFBE,  $DFDD,  $CFFC,  $BF1B,  $AF3A,  $9F59,  $8F78,
  48.                 $9188,  $81A9,  $B1CA,  $A1EB,  $D10C,  $C12D,  $F14E,  $E16F,
  49.                 $1080,  $00A1,  $30C2,  $20E3,  $5004,  $4025,  $7046,  $6067,
  50.                 $83B9,  $9398,  $A3FB,  $B3DA,  $C33D,  $D31C,  $E37F,  $F35E,
  51.                 $02B1,  $1290,  $22F3,  $32D2,  $4235,  $5214,  $6277,  $7256,
  52.                 $B5EA,  $A5CB,  $95A8,  $8589,  $F56E,  $E54F,  $D52C,  $C50D,
  53.                 $34E2,  $24C3,  $14A0,  $0481,  $7466,  $6447,  $5424,  $4405,
  54.                 $A7DB,  $B7FA,  $8799,  $97B8,  $E75F,  $F77E,  $C71D,  $D73C,
  55.                 $26D3,  $36F2,  $0691,  $16B0,  $6657,  $7676,  $4615,  $5634,
  56.                 $D94C,  $C96D,  $F90E,  $E92F,  $99C8,  $89E9,  $B98A,  $A9AB,
  57.                 $5844,  $4865,  $7806,  $6827,  $18C0,  $08E1,  $3882,  $28A3,
  58.                 $CB7D,  $DB5C,  $EB3F,  $FB1E,  $8BF9,  $9BD8,  $ABBB,  $BB9A,
  59.                 $4A75,  $5A54,  $6A37,  $7A16,  $0AF1,  $1AD0,  $2AB3,  $3A92,
  60.                 $FD2E,  $ED0F,  $DD6C,  $CD4D,  $BDAA,  $AD8B,  $9DE8,  $8DC9,
  61.                 $7C26,  $6C07,  $5C64,  $4C45,  $3CA2,  $2C83,  $1CE0,  $0CC1,
  62.                 $EF1F,  $FF3E,  $CF5D,  $DF7C,  $AF9B,  $BFBA,  $8FD9,  $9FF8,
  63.                 $6E17,  $7E36,  $4E55,  $5E74,  $2E93,  $3EB2,  $0ED1,  $1EF0
  64.               );
  65.  
  66. const
  67.   CRCTAB_32 : array [0..255] of longint
  68.             = ( $00000000, $77073096, $EE0E612C, $990951BA, $076DC419, $706AF48F, $E963A535, $9E6495A3,
  69.                 $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91,
  70.                 $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7,
  71.                 $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC, $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5,
  72.                 $3B6E20C8, $4C69105E, $D56041E4, $A2677172, $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B,
  73.                 $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940, $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59,
  74.                 $26D930AC, $51DE003A, $C8D75180, $BFD06116, $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
  75.                 $2802B89E, $5F058808, $C60CD9B2, $B10BE924, $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D,
  76.                 $76DC4190, $01DB7106, $98D220BC, $EFD5102A, $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433,
  77.                 $7807C9A2, $0F00F934, $9609A88E, $E10E9818, $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01,
  78.                 $6B6B51F4, $1C6C6162, $856530D8, $F262004E, $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457,
  79.                 $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C, $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65,
  80.                 $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2, $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB,
  81.                 $4369E96A, $346ED9FC, $AD678846, $DA60B8D0, $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
  82.                 $5005713C, $270241AA, $BE0B1010, $C90C2086, $5768B525, $206F85B3, $B966D409, $CE61E49F,
  83.                 $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD,
  84.                 $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, $EAD54739, $9DD277AF, $04DB2615, $73DC1683,
  85.                 $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8, $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1,
  86.                 $F00F9344, $8708A3D2, $1E01F268, $6906C2FE, $F762575D, $806567CB, $196C3671, $6E6B06E7,
  87.                 $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC, $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5,
  88.                 $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252, $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
  89.                 $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79,
  90.                 $CB61B38C, $BC66831A, $256FD2A0, $5268E236, $CC0C7795, $BB0B4703, $220216B9, $5505262F,
  91.                 $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D,
  92.                 $9B64C2B0, $EC63F226, $756AA39C, $026D930A, $9C0906A9, $EB0E363F, $72076785, $05005713,
  93.                 $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38, $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21,
  94.                 $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E, $81BE16CD, $F6B9265B, $6FB077E1, $18B74777,
  95.                 $88085AE6, $FF0F6A70, $66063BCA, $11010B5C, $8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
  96.                 $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, $A7672661, $D06016F7, $4969474D, $3E6E77DB,
  97.                 $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9,
  98.                 $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, $BAD03605, $CDD70693, $54DE5729, $23D967BF,
  99.                 $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94, $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D
  100.               );
  101.  
  102.  
  103. function CRC16 (B:byte; CRC:word):word; external;
  104. function CRC32 (B:byte; CRC:longint):longint; external;
  105. function CRC16BUF (BSEG,BOFS,BLEN:word; CRC:word):word; external;
  106. function CRC32BUF (BSEG,BOFS,BLEN:word; CRC:longint):longint; external;
  107.  
  108. {$L CRCTABLE.OBJ}
  109.  
  110. end.
  111.  
  112. comment &
  113.  
  114.     The codes is in two parts; the compiler specific interface
  115.     handlers and the routines that do the actual work.  By adding
  116.     new compiler interface handlers, the internal routines can work
  117.     with any compiler or even interpeted BASIC.
  118.  
  119.         The CRC16 and CRC32 routines get called from the high-level
  120.         language.  Their job is to call the UPDCRC16 and UPDCRC32 with
  121.     the proper register parameters.  The CRC16/32 routines then
  122.     reports the results in whatever manner the compiler expects
  123.     them.
  124.  
  125.     CRCxxBUF perform the same basic function as their CRCxx
  126.     routines except they are designed to work on data blocks
  127.     instead of one byte at a time.    The speed improvement comes
  128.     from not using compiler generated loops, which are not as fast
  129.     as they could be.
  130.  
  131.  
  132. comment &
  133.  
  134.         page        60,132
  135.  
  136. data            segment         byte public
  137.         extrn        CRCTAB_16:word
  138.         extrn        CRCTAB_32:dword
  139. data            ends
  140.  
  141. code        segment     word public
  142.         assume        cs:code,ds:data
  143.  
  144.         public        CRC16
  145.         public        CRC32
  146.         public        CRC16BUF
  147.         public        CRC32BUF
  148.  
  149. ;
  150. ;  function CRC16 (B : byte; CRC : word) : word;
  151. ;    begin
  152. ;      CRC16:=CRCTAB_16[((CRC shr 8) and $FF)] xor (CRC shl 8) xor B
  153. ;    end;
  154. ;
  155. ;  Uses    :   CX,DI,ES
  156. ;  Result  :   AX hold 16-bit CRC result
  157. ;
  158.  
  159. CRC        equ        bp+06                ; location of CRC16 parameter
  160. B        equ        bp+08                ; and the B byte paramter
  161.  
  162. crc16        proc        far
  163.         push        bp                ; save BP
  164.         mov        bp,sp                ; set up stack frame
  165.  
  166.         mov        ax,ds
  167.         mov        es,ax                ; REG.ES = seg(CRCTAB_16[])
  168.         mov        di,offset CRCTAB_16        ; REG.DI = ofs(CRCTAB_16[])
  169.  
  170.         mov        ax,[B]                ; REG.AX = word(B)
  171.         mov        cx,[CRC]            ; REG.CX = CRC
  172.         call        updCRC16            ; update CRC-16
  173.         mov        ax,cx                ; return result in AX
  174.  
  175.         pop        bp                ; restore stack frame
  176.         ret        4                ; return and pop parameters
  177. crc16        endp
  178.  
  179.  
  180. ;
  181. ;  TURBO PASCAL 4.x/5.x
  182. ;
  183. ;  function CRC32 (B : byte; CRC : longint) : longint;
  184. ;    begin
  185. ;      CRC32:=CRCTAB_32[byte(CRC) xor B] xor (CRC shr 8);
  186. ;    end;
  187. ;
  188. ;  Uses    :   BX,CX,DX,DI,ES
  189. ;  Result  :   DX:AX hold 32-bit CRC; DX holds MSB, AX holds LSB
  190. ;
  191.  
  192. CRC_LO        equ        bp+06                ; LSB of CRC parameter
  193. CRC_HI        equ        bp+08                ; MSB of CRC parameter
  194. B        equ        bp+10                ; and the B byte paramter
  195.  
  196. crc32        proc        far
  197.         push        bp                ; save BP
  198.         mov        bp,sp                ; set up stack frame
  199.  
  200.         mov        ax,ds
  201.         mov        es,ax                ; REG.ES = seg(CRCTAB_32[])
  202.         mov        di,offset CRCTAB_32        ; REG.DI = ofs(CRCTAB_32[])
  203.  
  204.                 mov             ax,[B]                          ; REG.BX = word(B)
  205.         xor        ah,ah                ; clear high byte
  206.         mov        cx,[CRC_LO]            ; REG.DXCX = CRC
  207.         mov        dx,[CRC_HI]
  208.         call        updCRC32            ; update CRC-32
  209.         mov        ax,cx                ; return result in DX:AX instead of DX:CX
  210.  
  211.         pop        bp                ; restore stack frame
  212.         ret        6                ; return and pop parameters
  213. crc32        endp
  214.  
  215.  
  216. ;
  217. ;  TURBO PASCAL 4.x/5.x
  218. ;
  219. ; function CRC16BUF (BSEG,BOFS,BLEN : word; CRC : word) : word;
  220. ;   begin
  221. ;     repeat
  222. ;    CRC:=CRC16(mem[BSEG:BOFS],CRC);
  223. ;    inc(BOFS);
  224. ;    dec(BLEN);
  225. ;     until BLEN=0
  226. ;     CRC16BUF:=CRC;
  227. ;   end;
  228. ;
  229.  
  230. CRC        equ        bp+6
  231. BLEN        equ        bp+8
  232. BOFS        equ        bp+10
  233. BSEG        equ        bp+12
  234.  
  235. crc16buf    proc        far
  236.         push        bp                ; save BP
  237.         mov        bp,sp                ; set up stack frame
  238.  
  239.         mov        ax,ds
  240.         mov        es,ax                ; REG.ES = seg(CRCTAB_16[])
  241.         mov        di,offset CRCTAB_16        ; REG.DI = ofs(CRCTAB_16[])
  242.  
  243.         mov        ax,[BLEN]            ; get buffer length
  244.         mov        cx,[CRC]            ; get current CRC value
  245.                 mov             ds,[BSEG]                       ; get buffer segment
  246.         mov        si,[BOFS]            ; get buffer offset
  247.  
  248.         call        bufCRC16            ; figure CRC for a buffer
  249.  
  250.         mov        ax,es                ; restore DS
  251.         mov        ds,ax
  252.  
  253.         mov        ax,cx                ; return CRC result in AX
  254.         pop        bp                ; restore stack frame
  255.                 ret             8
  256. crc16buf        endp
  257.  
  258.  
  259. ;
  260. ;  TURBO PASCAL 4.x/5.x
  261. ;
  262. ; function CRC32BUF (BSEG,BOFS,BLEN : word; CRC : longint) : longint;
  263. ;   begin
  264. ;     repeat
  265. ;    CRC:=CRC32(mem[BSEG:BOFS],CRC);
  266. ;    inc(BOFS);
  267. ;    dec(BLEN);
  268. ;     until BLEN=0
  269. ;     CRC32BUF:=CRC;
  270. ;   end;
  271. ;
  272.  
  273. CRC_LO        equ        bp+6
  274. CRC_HI        equ        bp+8
  275. BLEN        equ        bp+10
  276. BOFS        equ        bp+12
  277. BSEG        equ        bp+14
  278.  
  279. crc32buf    proc        far
  280.         push        bp                ; save BP
  281.         mov        bp,sp                ; set up stack frame
  282.  
  283.         mov        ax,ds
  284.         mov        es,ax                ; REG.ES = seg(CRCTAB_32[])
  285.         mov        di,offset CRCTAB_32        ; REG.DI = ofs(CRCTAB_32[])
  286.  
  287.         mov        ax,[BLEN]            ; get buffer length
  288.         mov        cx,[CRC_LO]            ; get current CRC value
  289.         mov        dx,[CRC_HI]
  290.                 mov             ds,[BSEG]                       ; get buffer segment
  291.         mov        si,[BOFS]            ; get buffer offset
  292.  
  293.         call        bufCRC32            ; figure CRC for a buffer
  294.  
  295.         mov        ax,es                ; restore DS
  296.         mov        ds,ax
  297.  
  298.         mov        ax,cx                ; return CRC result in DX:AX
  299.                 pop             bp                              ; restore stack frame
  300.                 ret             10
  301. crc32buf    endp
  302.  
  303. ;
  304. ;  BUFCRC16, BUFCRC32, UPDCRC16, and UPDCRC32 routines presented here
  305. ;  should not be changed when porting the code to different compilers.
  306. ;
  307.  
  308.  
  309. ;
  310. ; BUFCRC16
  311. ;
  312. ;   AX    <- length of data buffer
  313. ;   CX      <- current CRC-16 value
  314. ;   DS:SI <- pointer to start of data buffer
  315. ;   ES:DI <- pointer to start of 16-bit CRC table
  316. ;   AX      -> last character CRC'd
  317. ;   BX      -> destroyed
  318. ;   CX      -> resulting CRC-16
  319. ;   DS:SI -> points to byte after buffer
  320. ;
  321.  
  322. bufCRC16    proc        near
  323.         mov        dx,ax                ; get buffer counter in DX
  324.         cld                        ; incremental string operation
  325. nextch16:    lodsb                        ; get character from buffer
  326.         call        updCRC16            ; update CRC-16
  327.         dec        dx                ; decrement buffer count
  328.         jnz        nextch16            ; jump if DX!=0
  329.         ret
  330. bufCRC16    endp
  331.  
  332.  
  333. ;
  334. ; BUFCRC32
  335. ;
  336. ;   AX    <- length of data buffer
  337. ;   DX:CX <- current CRC-32 value
  338. ;   DS:SI <- pointer to start of data buffer
  339. ;   ES:DI <- pointer to start of 16-bit CRC table
  340. ;   AX      -> last character CRC'd
  341. ;   BX      -> zero
  342. ;   DX:CX -> resulting CRC-32
  343. ;   DS:SI -> points to byte after buffer
  344. ;
  345.  
  346. bufCRC32    proc        near
  347.         mov        bx,ax                ; put buffer count in BX
  348.         cld                        ; incremental string operation
  349. nextch32:    push        bx                ; put count on stack
  350.         lodsb                        ; get character from buffer
  351.         call        updCRC32            ; update CRC-32
  352.         pop        bx                ; get buffer count
  353.         dec        bx                ; decrement buffer count
  354.         jnz        nextch32            ; jump if BX!=0
  355.                 ret
  356. bufCRC32    endp
  357.  
  358.  
  359. ;
  360. ; UPDCRC16
  361. ;
  362. ;   AL      <- character to add
  363. ;   CX      <- current CRC-16 value
  364. ;   ES:DI <- pointer to start of 16-bit CRC table
  365. ;   CX      -> resulting CRC-16
  366. ;
  367.  
  368. updCRC16        proc            near
  369.         mov        bl,ch                ; REG.BL = (CRC shr 8)
  370.         xor        bh,bh                ; REG.BX = (CRC shr 8) and $FF
  371.         mov        ch,cl                ; REG.CX = (CRC shl 8)
  372.         mov        cl,al                ; REG.CX = (CRC shl 8) xor B
  373.                 shl             bx,1                            ; set REG.BX to index a table of WORD values
  374.         xor        cx,word ptr es:[di+bx]        ; REG.BX = CRCTAB_16[(CRC shr 8) and $FF] xor (CRC shl 8) xor B
  375.                 ret
  376. updCRC16        endp
  377.  
  378.  
  379. ;
  380. ; UPDCRC32
  381. ;
  382. ;   AL      <- character to add
  383. ;   DX:CX <- current CRC-32 value
  384. ;   ES:DI <- pointer to start of 32-bit CRC table
  385. ;   DX:CX -> resulting CRC-32
  386. ;
  387.  
  388. updCRC32    proc        near
  389.         xor        al,cl                ; REG.AL = byte(CRC) xor B
  390.         mov        bl,al                ; REG.BL = byte(CRC) xor B
  391.         mov        cl,ch                ; A B C-C  \  REG.DXCX = CRC shr 8
  392.         mov        ch,dl                ; A B-B C   >
  393.         mov        dl,dh                ; A-A B C  /  move over one byte
  394.         xor        dh,dh                ; 0 A B C /
  395.         mov        bh,dh                ; REG.BX = byte(CRC) xor B
  396.                 shl             bx,1                            ; adjust to index dword table
  397.                 shl             bx,1
  398.         xor        cx,es:[di+bx]            ; REG.DXCX = CRCTAB_32[(byte(CRC) xor B] xor (CRC shr 8)
  399.         xor        dx,es:[di+bx+2]
  400.         ret
  401. updCRC32    endp
  402. code        ends
  403.  
  404.         end
  405.  
  406.  
  407.   The following text is the file from which the tables and lookup
  408.   methods were derived from.  My copy of this files seems to be
  409.   incomplete; it mentions that code to generate the table at run-time
  410.   is shown later but is not.
  411.  
  412.  
  413.  
  414.   /* ============================================================= */
  415.   /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
  416.   /*  code or tables extracted from it, as desired without restriction.     */
  417.   /*                                                                        */
  418.   /*  First, the polynomial itself and its table of feedback terms.  The    */
  419.   /*  polynomial is                                                         */
  420.   /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
  421.   /*                                                                        */
  422.   /*  Note that we take it "backwards" and put the highest-order term in    */
  423.   /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
  424.   /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
  425.   /*  the MSB being 1.                                                      */
  426.   /*                                                                        */
  427.   /*  Note that the usual hardware shift register implementation, which     */
  428.   /*  is what we're using (we're merely optimizing it by doing eight-bit    */
  429.   /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
  430.   /*  implementation, that means shifting towards the right.  Why do we     */
  431.   /*  do it this way?  Because the calculated CRC must be transmitted in    */
  432.   /*  order from highest-order term to lowest-order term.  UARTs transmit   */
  433.   /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
  434.   /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
  435.   /*  sends each low-bit to hight-bit; and the result is transmission bit   */
  436.   /*  by bit from highest- to lowest-order term without requiring any bit   */
  437.   /*  shuffling on our part.  Reception works similarly.                    */
  438.   /*                                                                        */
  439.   /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
  440.   /*                                                                        */
  441.   /*      The table can be generated at runtime if desired; code to do so   */
  442.   /*      is shown later.  It might not be obvious, but the feedback        */
  443.   /*      terms simply represent the results of eight shift/xor opera-      */
  444.   /*      tions for all combinations of data and CRC register values.       */
  445.   /*                                                                        */
  446.   /*      The values must be right-shifted by eight bits by the "updcrc"    */
  447.   /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
  448.   /*      hardware you could probably optimize the shift in assembler by    */
  449.   /*      using byte-swap instructions.                                     */
  450.   /*      polynomial $edb88320                                              */
  451.   /*                                                                        */
  452.   /*  --------------------------------------------------------------------  */
  453.  
  454. long crc_32_tab[] = {
  455.       0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  456.       0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  457.       0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  458.       0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  459.       0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  460.       0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  461.       0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  462.       0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  463.       0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  464.       0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  465.       0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  466.       0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  467.       0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  468.       0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  469.       0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  470.       0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  471.       0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  472.       0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  473.       0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  474.       0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  475.       0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  476.       0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  477.       0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  478.       0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  479.       0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  480.       0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  481.       0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  482.       0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  483.       0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  484.       0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  485.       0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  486.       0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  487.       0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  488.       0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  489.       0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  490.       0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  491.       0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  492.       0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  493.       0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  494.       0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  495.       0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  496.       0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  497.       0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  498.       0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  499.       0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  500.       0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  501.       0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  502.       0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  503.       0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  504.       0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  505.       0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  506.       0x2d02ef8dL
  507.    };
  508.  
  509. #define UPDCRC32(res,oct) res=crc_32_tab[(byte)res^(byte)oct] ^ ((res>>8) & 0x00FFFFFFL)
  510.  
  511.  
  512.